%::PROVIDES=(
	name	=> ["HANDLE_ALERT"],
	desc	=> ["Handle HANDLE_ALERT requests"],
	type	=> "request",
	code	=> \&::do_handle_alert
);

#########################################################################
# The alert expects the following argument and is mandatory:		#
# TYPE : This can be any of: APP_START[x],APP_STOP[x],APP_FAIL[x] or	#
# 	  CLUSTER_START[x], CLUSTER_STOP[x], CLUSTER_PARTITIONED[x],	#
# 	  NODE_JOIN[x], NODE_LEAVE[x], NODE_FAIL[x]			#
#	  NODE_HB_WARN[x], NODE_HB_FAIL[x], NODE_HB_OK[x],		#
#	  NODE_NET_FAIL[x], NODE_NET_SWAP[x],				#
#	  NODE_SSH_WARN[x], NODE_SSH_FAIL[x]				#
#									#
# For NODE requests the following arguments are expected:		#
# NODE - the name of the node in question.				#
# For CLUSTER requests:							#
# None 									#
# For APP requests:							#
# APP - The name of the application.					#
#									#
# Any request may include the optional INFO to show more information.	#
# For NODE_NET_* messages the info includes "NETWORK: name" for FAIL	#
# and "NETWORK: name OLD: card NEW: card" for SWAP.			#
# The cluster configuration must contain details of how the alert	#
# is handled, but for now just an email to root will be generated.	#
#########################################################################
{
my $mailer;
my $last_alert_time=0;
my %last_alert_args=();
my $net_smtp=1;
eval "use Net::SMTP;";
if($@) {
	$net_smtp=0;
}

sub ::do_handle_alert {
my $args=shift;
my ($h,@node,$app);
my @T=qw(
	APP_START APP_STOP APP_FAIL
	CLUSTER_START CLUSTER_STOP CLUSTER_PARTITIONED CLUSTER_UNPARTITIONED
	NODE_JOIN NODE_LEAVE NODE_FAIL
	NODE_HB_WARN NODE_HB_FAIL NODE_HB_OK
	NODE_NET_FAIL NODE_NET_SWAP
	NODE_SSH_FAIL NODE_SSH_WARN
	);

	#################################################################
	# We check to see if the last alert was a duplicate of the	#
	# current one and ignore if it is and it has occured in the	#
	# last 10 minutes.						#
	#################################################################

	my $duplicate=1;
	if($last_alert_time+600<time) {
		$duplicate=0; # older than 10 mins, so always not a duplicate
	}
	for my $ckey (keys %$args) {
		next if $ckey eq "INFO"; # don't take into account for duplicates
		if(!exists($last_alert_args{$ckey})) {
			$duplicate=0; last;
		}
		if($last_alert_args{$ckey} ne $args->{$ckey}) {
			$duplicate=0; last;
		}
	}
	$last_alert_time=time;
	if(! $duplicate) {
		%last_alert_args=();
		for my $ckey (keys %$args) {
			next if $ckey eq "INFO"; # don't take into account for duplicates
			$last_alert_args{$ckey}=$args->{$ckey};
		}
	} else {
		return "OK";
	}
	if(!exists($xml->{global}->{alert_to})) {
		return "OK";
	}
	my $send_to_file=0;
	my $email_to=$xml->{global}->{alert_to};
	if(defined($email_to) && substr($email_to,0,1) eq "/") {
		$send_to_file=1;
	}
	my $date_format='%d-%m-%Y %H:%M:%S';
	if(exists($xml->{global}->{alert_date_format}) &&
	   defined($xml->{global}->{alert_date_format})) {
		$date_format=$xml->{global}->{alert_date_format};
	}
	my $date=strftime($date_format,localtime(time));
	if($send_to_file==0) {
		if(!defined($email_to)) {
			$email_to="root";
		}
		$email_to =~ s/\s+//g;
		if(!length($email_to)) {
			$email_to="root";
		}
	}
	if(!exists($args->{TYPE})) {
		logwarn("HANDLE_ALERT missing TYPE argument");
		return "MISSING_ARG";
	}

	$h=hostname;

	if(! grep {$_ eq $args->{TYPE}} @T) {
		logwarn("HANDLE_ALERT TYPE is not recognised [$args{TYPE}]");
		return "UNKNOWN_TYPE";
	}

	if($args->{TYPE} =~ /^NODE/) {
		if(!exists($args->{NODE})) {
			logwarn("HANDLE_ALERT TYPE NODE missing NODE argument");
			return "MISSING_ARG";
		}
		$node=$args->{NODE};
	}

	if($args->{TYPE} =~ /^APP/) {
		if(!exists($args->{APP})) {
			logwarn("HANDLE_ALERT TYPE APP missing APP argument");
			return "MISSING_ARG";
		}
		$app=$args->{APP};
	}

	#################################################################
	# Now we check to see what command we can use to send the	#
	# email .							#
	#################################################################
	if($send_to_file==0 && !defined($mailer)) {
		for my $f ("/usr/bin/mailx","/bin/mailx") {
			$mailer=$f if -x $f;
			last if $mailer;
		}
		if(!defined($mailer)) {
			logwarn("Unable to find binary to send an email.");
			return "MISSING_BINARY";
		}
	}

	my $fd;
	if($send_to_file) {
		if(!open($fd,">>$email_to")) {
			return "FAIL Can not open file for writing.";
		}
	} else {
		if($net_smtp && $email_to =~ /^SMTP\s+/) {
			my @I=split(/\s+/,$email_to);
			my @to=('root');
			if($I>2) {
				@to=split(/,/,$I[2]);
			}
			$fd=Net::SMTP->new($I[1]);
			if($fd) {
				$fd->to(@to);
				$fd->data();
				$fd->datasend("To: $I[2]\n");
				$fd->datasend("Subject: CLUSTER_EVENT: $args->{TYPE}\n");
				$fd->datasend("\n");
				$fd->datasend("CLUSTER     : $xml->{global}->{name}\n");
				$fd->datasend("EVENT       : $args->{TYPE}\n");
				$fd->datasend("DATE/TIME   : $date\n");
				if($args->{TYPE} =~ /^NODE/) {
					$fd->datasend("NODE        : $args->{NODE}\n");
				} elsif($args->{TYPE} =~ /^APP/) {
					$fd->datasend("APPLICATION : $args->{APP}\n");
				}
				if($args->{TYPE} =~ /^(APP|CLUSTER)/) {
					if(exists($args->{NODE})) {
						$fd->datasend("NODE        : $args->{NODE}\n");
					}
				}
				if(exists($args->{INFO})) {
					my $i=$args->{INFO};
					my ($d)=($i =~ /^HEX:(.*)/);
					if(defined($d) && length($d)) {
						$i=pack("H*",$1);
					}
					$fd->datasend("INFO        : $i\n");
				}
				$fd->dataend();
				$fd->quit;
			}
			return "OK";
		} else {
			open($fd,"|$mailer -s 'CLUSTER_EVENT: $args->{TYPE}' $email_to");
		}
	}
	print $fd "CLUSTER     : $xml->{global}->{name}\n";
	print $fd "EVENT       : $args->{TYPE}\n";
	print $fd "DATE/TIME   : $date\n";
	if($args->{TYPE} =~ /^NODE/) {
		print $fd "NODE        : ",$args->{NODE},"\n";
	} elsif($args->{TYPE} =~ /^APP/) {
		print $fd "APPLICATION : ",$args->{APP},"\n";
	}
	if($args->{TYPE} =~ /^(APP|CLUSTER)/) {
		if(exists($args->{NODE})) {
			print $fd "NODE        : ",$args->{NODE},"\n";
		}
	}
	if(exists($args->{INFO})) {
		my $i=$args->{INFO};
		my ($d)=($i =~ /^HEX:(.*)/);
		if(defined($d) && length($d)) {
			$i=pack("H*",$1);
		}
		print $fd "INFO        : $i\n";
	}
	close($fd);
	return "OK";
}

}

1;
